#include <myheader_c_plus.h>
using std::cout;
using std::ostream;
using std::istream;
using std::endl;
class CharProxy;
//begin of ths CowString 
class CowString {
public:
    //默认构造函数
    CowString()
        :_pstr(new char[1 + 4] + 4)
    {
        *(int *)(_pstr - 4) = 1;

    }
    //构造函数
    CowString(const char * pstr)
        :_pstr(new char[strlen(pstr) + 1 + 4]() + 4)
    {
        strcpy(_pstr, pstr);
        *(int *)(_pstr - 4) = 1;
    }

    //拷贝构造函数CowString s1 = s2;
    CowString (const CowString & rhs)
        :_pstr(rhs._pstr)
    {
        //引用计数+1
        *(int *)(_pstr - 4) += 1;
    }

    //析构函数
    ~CowString(){
        //判断是否引用计数值到0
        // *(int *)(_pstr - 4) -= 1;
        if(--*(int *)(_pstr - 4) == 0){
            delete (_pstr - 4);
            _pstr = nullptr;
        }
    }

    //赋值运算符s1 = s2,修改内容
    CowString & operator=(const CowString & rhs){
        //判断是否是自赋值
        if(this != &rhs){
            *(int *)(_pstr - 4) -= 1;
            //判断引用计数是否为0
            if(*(int *)(_pstr - 4) == 0){
                delete (_pstr - 4);
            }
            _pstr = rhs._pstr;
            *(int *)(_pstr - 4) += 1;
        }
        return *this;
    }

    int getCount(){
        return *(int *)(_pstr - 4);
    }

    void print(){
        cout << _pstr << endl;
    }

    friend ostream & operator<<(ostream & os, const CowString & rhs);

private:

    //begin of the CharProxy
    class CharProxy{
    public:
        //构造函数
        CharProxy(CowString & cs, size_t idx)
            :_cs(cs)
             ,_idx(idx)
        {

        }
        //运算符重载=,属于是写操作，要进行写时复制
        char & operator=(const char & c){
            if(_idx < strlen(_cs._pstr)){
                //判断是否引用大于1.若大于1，则需要进行复制
                if(_cs.getCount() > 1){
                    char * ptemp = new char [strlen(_cs._pstr+ 1 + 4)]() + 4;
                    strcpy(ptemp, _cs._pstr);
                    //将原来的计数值-1
                    *(int *)(_cs._pstr - 4) -= 1;
                    _cs._pstr = ptemp;
                    ptemp = nullptr;
                    //新的计数值变成1
                    *(int *)(_cs._pstr - 4) = 1;
                }
                _cs._pstr[_idx] = c;
                return _cs._pstr[_idx];

            }else{
                static char ch = '\0';
                return ch;
            }
        }

        friend ostream & operator<<(ostream & os, const CowString::CharProxy & rhs);
    private:
        CowString & _cs;
        size_t _idx;

    };
    //end of the CharProxy

    char * _pstr;

public:
    //重载运算符[],这时候引入嵌套类
    CharProxy operator[](size_t idx){
        return CharProxy(*this, idx);
    }

    friend ostream & operator<<(ostream & os, const CowString::CharProxy & rhs);
};
//end of the CowString

//重载<< 输出流
ostream & operator<<(ostream & os, const CowString & rhs){
    if(rhs._pstr != nullptr){
        os << rhs._pstr;
    }
    return os;
}

//运算符重载<< 
ostream & operator<<(ostream & os, const CowString::CharProxy & rhs){
    if(rhs._cs._pstr){
        os << rhs._cs._pstr[rhs._idx];
    }
    return os;
}
int main(int argc, char *argv[])
{
    CowString s1("hello");
    s1.print();
    cout << s1.getCount() << endl;
    CowString s2 = s1;
    s2.print();
    cout << s1.getCount() << endl;
    cout << s2.getCount() << endl;
    CowString s3;
    s3 = s1;
    s3.print();
    cout << s3.getCount() << endl;

    cout <<"======================" << endl;
    CowString s4("world");
    cout << s4.getCount() << endl;
    CowString s5;
    s5 = s4;
    cout << s4.getCount() << endl;
    cout << s5.getCount() << endl;
    s4[0] = 'W';
    cout << s4 << endl;
    cout << s4.getCount() << endl;
    cout << s5.getCount() << endl;
    cout << "========================" << endl;
    CowString s6;
    s6 = s4;
    cout << s6.getCount() << endl;
    cout << s4.getCount() << endl;
    cout << s4[2] << endl;
    cout << s6.getCount() << endl;
    cout << s4.getCount() << endl;
    return 0;
}

